﻿using Pay.Core;
using Pay.Data;
using Pay.DTO;
using Pay.IService;
using Pay.Service.Cache;
using Pay.TO;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Pay.Service {
    public class AdvertisementService : ServiceBase, IAdvertisementService, IDisposable {
        private IUnitOfWork _iUnitOfWork;
        private ISoupTaskService _iSoupTaskService;
        public AdvertisementService(IUnitOfWork iUnitOfWork, ISoupTaskService iSoupTaskService) : base(iUnitOfWork) {
            _iUnitOfWork = iUnitOfWork;
            _iSoupTaskService = iSoupTaskService;
        }

        /// <summary>
        /// 获得广告列表
        /// </summary>
        /// <param name="query"></param>
        /// <returns></returns>
        public PagedResult<advertisement_dto> GetAdvertisements(AdvertisementQuery query) {
            AutoUpdateAdvertisement();
            var filter = PredicateBuilder.True<Advertisement>();
            if (!string.IsNullOrEmpty(query.position_type)) {
                int value = int.Parse(query.position_type);
                filter = filter.And(c => c.PositionType == (EAdvertisementPositionType)value);
            }
            if (!string.IsNullOrEmpty(query.status)) {
                int value = int.Parse(query.status);
                filter = filter.And(c => c.Status == (EAdvertisementStatus)value);
            }
            if (!string.IsNullOrEmpty(query.begin_time)) {
                DateTime time = DateTime.Parse(query.begin_time);
                filter = filter.And(c => c.CreateTime >= time);
            }
            if (!string.IsNullOrEmpty(query.end_time)) {
                DateTime time = DateTime.Parse(query.end_time).AddDays(1);
                filter = filter.And(c => c.CreateTime <= time);
            }
            var result = context.Advertisement.FromCachePaged<Advertisement, advertisement_dto>(query.page, query.size, filter, orderBy => orderBy.OrderBy(o => o.PositionType).ThenBy(o => o.Sort));
            return result;
        }

        /// <summary>
        /// 获得广告
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public advertisement_dto GetAdvertisement(long id) {
            return context.Advertisement.Find(id).ToDtoObject<advertisement_dto>();
        }

        /// <summary>
        /// 新增广告
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public int AddAdvertisement(advertisement_dto dto) {
            dto.create_time = DateTime.Now;
            if (dto.end_time != null && dto.end_time < dto.begin_time)
                throw new ServerErrorException("自动失效时间 必须大于 自动开始时间");
            if(dto.begin_time <= DateTime.Now && (dto.end_time == null || dto.end_time >= DateTime.Now)) {
                dto.status = EAdvertisementStatus.Normal;
            } else {
                dto.status = EAdvertisementStatus.Stopping;
            }
            Advertisement model = new Advertisement();
            dto.ToDtoObject(model);
            context.Advertisement.Add(model);
            int result = _iUnitOfWork.Commit("Advertisement");
            return result;
        }

        /// <summary>
        /// 更新广告
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public int UpdateAdvertisement(advertisement_dto dto) {
            if (dto.end_time != null && dto.end_time < dto.begin_time)
                throw new ServerErrorException("自动失效时间 必须大于 自动开始时间");
            if (dto.begin_time <= DateTime.Now && (dto.end_time == null || dto.end_time >= DateTime.Now)) {
                dto.status = EAdvertisementStatus.Normal;
            } else {
                dto.status = EAdvertisementStatus.Stopping;
            }
            Advertisement model = context.Advertisement.FindById(dto.id);
            dto.ToDtoObject(model);
            int result = _iUnitOfWork.Commit("Advertisement");
            return result;
        }

        /// <summary>
        /// 删除广告
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public int DeleteAdvertisement(long id) {
            var merchIntroduce = context.Advertisement.FindById(id);
            context.Advertisement.Remove(merchIntroduce);
            int result = _iUnitOfWork.Commit("Advertisement");
            return result;
        }

        /// <summary>
        /// 修改广告状态
        /// </summary>
        /// <param name="id"></param>
        /// <param name="status"></param>
        /// <returns></returns>
        public int UpdateAdvertisementStatus(long id, int status) {
            Advertisement model = context.Advertisement.FindById(id);
            model.Status = (EAdvertisementStatus)(status);
            if(model.Status == EAdvertisementStatus.Stopping) {
                model.EndTime = DateTime.Now;
                if (model.BeginTime > model.EndTime)
                    model.BeginTime = ((DateTime)model.EndTime).AddDays(-1);
            }
            int result = _iUnitOfWork.Commit("Advertisement");
            return result;
        }

        #region API接口
        /// <summary>
        /// APP端根据位置类型获得广告列表
        /// </summary>
        /// <param name="positionType"></param>
        /// <returns></returns>
        public List<ad_dto> AppGetAdvertisementList(merch_advertisement_query_type queryType) {
            var filter = PredicateBuilder.True<Advertisement>();
            filter = filter.And(o => (int)o.PositionType == queryType.position_type);
            if (queryType.is_type) filter = filter.And(o => o.IsAppStoreShow == true);
            var list = context.Advertisement.Where(filter).OrderBy(o => o.Sort).FromCache<Advertisement, Advertisement>("Advertisement") ?? new List<Advertisement>();
            //用当前时间判断状态，取出缓存后再判断
            DateTime now = DateTime.Now;
            var result = list.Where(o => o.BeginTime <= DateTime.Now && (o.EndTime == null || o.EndTime >= DateTime.Now)).ToDtoList<ad_dto>();
            return result;
        }
        /// <summary>
        /// App端根据（多个）位置类型获得广告列表
        /// </summary>
        /// <param name="types"></param>
        /// <returns></returns>
        public List<ad_type_dto> AppGetAdListByTypes(List<int> types) {
            if (types == null) types = new List<int>();
            var results = new List<ad_type_dto>();
            var advertisementList = context.Advertisement.Where(o => types.Contains((int)o.PositionType))
                .FromCache<Advertisement, advertisement_dto>("Advertisement") ?? new List<advertisement_dto>();
            //用当前时间判断状态，取出缓存后再判断
            DateTime now = DateTime.Now;
            advertisementList = advertisementList.Where(o => o.begin_time <= DateTime.Now && (o.end_time == null || o.end_time >= DateTime.Now)).ToList() ?? new List<advertisement_dto>();

            foreach (var type in types) {
                ad_type_dto model = new ad_type_dto();
                model.type = type;
                model.ad_list = advertisementList.Where(o => o.position_type == (EAdvertisementPositionType)type).OrderBy(o => o.sort).ToDtoList<ad_dto>();
                results.Add(model);
            }
            return results;
        }

        /// <summary>
        /// APP端获取广告详情（用于记录点击数）
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public advertisement_dto AppGetAdvertisement(long id) {
            var result = context.Advertisement.Where(o => o.Id == id).FirstOrDefault();
            result.ClickNum = result.ClickNum + 1;
            _iUnitOfWork.Commit();
            return result.ToDtoObject<advertisement_dto>();
        }
        #endregion


        /// <summary>
        /// 自动广告状态
        /// </summary>
        private void AutoUpdateAdvertisement() {
            var list = context.Advertisement.ToList();
            if (list != null && list.Count() > 0) {
                bool isNeedCommit = false;
                foreach (var ad in list) {
                    if (ad.BeginTime <= DateTime.Now && (ad.EndTime == null || ad.EndTime >= DateTime.Now) && ad.Status != EAdvertisementStatus.Normal) {//正常
                        ad.Status = EAdvertisementStatus.Normal;
                        isNeedCommit = true;
                    }else if ((ad.BeginTime > DateTime.Now || (ad.EndTime != null && ad.EndTime < DateTime.Now)) && ad.Status != EAdvertisementStatus.Stopping) {//停用
                        ad.Status = EAdvertisementStatus.Stopping;
                        isNeedCommit = true;
                    }
                }
                if (isNeedCommit)
                    _iUnitOfWork.Commit("Advertisement");
            }
        }
    }
}
